Skip to content

feat(codex): start a codex session at a chosen reasoning effort - #515

Merged
Ark0N merged 2 commits into
Ark0N:masterfrom
irisitymichaelgrundberg:feat/codex-reasoning-effort
Oct 4, 2026
Merged

Ark0N merged 2 commits into
Ark0N:masterfrom
irisitymichaelgrundberg:feat/codex-reasoning-effort

Conversation

@irisitymichaelgrundberg

@irisitymichaelgrundberg irisitymichaelgrundberg commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Part of #513 (the Codex half).

codexConfig takes a new reasoningEffort, and a codex session starts with --config model_reasoning_effort=<level>.

Why

A caller can pick codex's model per session through codexConfig.model, but not its reasoning effort, so every session starts at whatever ~/.codex/config.toml says. Claude sessions already take an effort per session through effort.

What it does

  • CODEX_REASONING_EFFORTS in src/types/session.ts lists the levels codex accepts as of codex-cli 0.154.0: none, minimal, low, medium, high, xhigh, max and ultra. Which of them a given model honours is codex's call. CodexConfig gets a matching reasoningEffort field.
  • The schema admits only those words. CodexConfigSchema validates reasoningEffort as an enum built from that list, so both POST /api/sessions and POST /api/quick-start reject anything else.
  • The registry emits one literal per level. An argv token can't splice a parameter into a literal, and codex wants model_reasoning_effort=<level> as one --config value. The Codex entry therefore declares a reasoningEffort enum parameter and one --config model_reasoning_effort=<level> argument per level, each gated on its own value. A level the enum doesn't know emits nothing. The registry needed no new argument shape for this.
  • The arguments come after --model and before the resume <id> subcommand, so a resumed session keeps its effort too.

The "Codex specifics" list in docs/architecture-invariants.md now names the two --config values codex takes from codexConfig. codexConfig already round-trips through SessionState, so the effort survives a respawn and a Codeman restart. npm run generate:cli-catalog -- --check reports the catalogue in sync, because launch arguments aren't part of it.

Testing

  • npm test passes, as do typecheck, lint, format and the catalogue check.
  • test/cli-registry-spawn-golden.test.ts gains two cases:
    • one renders the launch command for every level;
    • one pins the order with a model and a resume id, codex --model gpt-5 --config model_reasoning_effort=high resume roll_42.
  • The new test/codex-reasoning-effort-schema.test.ts checks that both create schemas accept every level, and that both reject unknown words and shell characters.
  • test/routes/external-cli-bypass-clamp.test.ts checks that a non-granted owner in multi-user mode keeps the effort when the clamp forces bypass off.
  • By hand, codex --config model_reasoning_effort=xhigh starts codex-cli 0.154.0 with gpt-5.6-sol xhigh in its header, where the user config says medium. Codex needs no extra quoting around the level.

No changeset, following the repository's convention for contributors.

🤖 Generated with Claude Code

codexConfig takes a `reasoningEffort`, one of the levels codex accepts,
and the session starts with `--config model_reasoning_effort=<level>`.
The registry declares one literal per level, gated on the enum, because
an argv token cannot splice a value into a literal.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ser clamp

Both create schemas now refuse an unknown level, and a non-granted owner's
codexConfig keeps its reasoningEffort when the clamp forces bypass off.
docs/architecture-invariants.md lists the two --config values codex now
takes from codexConfig.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@irisitymichaelgrundberg
irisitymichaelgrundberg marked this pull request as ready for review October 2, 2026 04:49
@Ark0N
Ark0N merged commit e082d8e into Ark0N:master Oct 4, 2026
2 checks passed
Ark0N pushed a commit that referenced this pull request Oct 4, 2026
…dvisor (#514, #515, #530 landing)

Maintainer merge-time fixes for the three PRs that landed together on the
session create / launch / persistence path.

#514 findings (bot verdict merge-with-fixes):
- minor, fixed: SessionState.model was published and persisted for every
  mode, so a codex/opencode cron session reported the app-wide Claude
  default it never ran on. toState() now emits it only where the new
  cliTakesSessionModel() holds (registry capability model.source ===
  'claude-settings-file', no CLI id branch). POST /api/sessions uses the
  same helper for its non-claude refusal, so refusal and publication cannot
  drift. Recovery then hands back undefined for other modes on its own.
- nit, fixed: the `model` schema admitted a leading dash (and '.', '[').
  The first character must now be a letter or digit; still a subset of the
  registry's model-claude pattern, so nothing accepted is refused at launch.
- nit, fixed (reject, the consistent choice): `model` with
  attachRemoteSession was silently dropped. Now a 400 INVALID_INPUT, as
  #514 does for non-claude CLIs and quick-start does for remote cases.
  advisorModel (#530) gets the same refusal there. effort and envOverrides
  keep their older silent ignore on that branch so no existing caller breaks.

#515 finding (bot verdict merge, one nit):
- nit, fixed: the types/session.ts @fileoverview described CodexConfig as
  (model, resumeSessionId); it now lists reasoningEffort, bypass,
  animations and renderMode too.

Audit of the merged combination (not reviewed before):
- The conflict resolutions in session.ts (toState), types/session.ts,
  reboot-restore-routes.ts, server.ts (restoreMuxSessions), CLAUDE.md and
  skills/codeman/reference/endpoints.md (+ plugin mirror) keep both sides
  correctly; nothing was lost or doubled.
- A claude session with both `model` and `advisorModel` launches with
  `--model <id>` and ONE merged `--settings` JSON (ultracode + advisorModel,
  or advisorModel beside `--effort <level>`), on the tmux template
  (including the resume || new variant and with the statusLine exporter)
  and on the direct-PTY fallback. Both values (and effort) survive
  restoreMuxSessions onto a dead pane, a reboot restore into a fresh pane,
  and restartCli/dead-pane respawn via _buildRespawnPaneOptions.
- quick-start and ralph-loop take no per-session `model` (matching #514's
  scope, POST /api/sessions only) and launch on the app-wide default, which
  toState now persists for claude, so recovery stays consistent.
- No defect found in the combination beyond the findings above. Noted, not
  changed: advisorModel is still published for any mode a caller sends it
  with (launch-inert there; the UI and skill send it for claude only).

Tests: test/session-model-recovery.test.ts pins the pair through both
recovery shapes for effort ultracode/high/none, the recovery constructors'
fields, the tmux-manager builder hop, and the codex/opencode/shell
non-publication; test/advisor-model.test.ts pins the launch lines and a
real direct-PTY Session's pty.spawn argv; the route test covers flag-shaped
models, attach refusals and the published fields. Docs: SessionState.model
docstring, the reboot-restore-registry header, the golden test comment and
the CLAUDE.md model/advisor bullets.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Ark0N pushed a commit that referenced this pull request Oct 4, 2026
…#520, #521, #522, #523, #524, #530, #531)

One consolidated minor changeset with the Thanks block first; the four contributor changesets (#520, #521, #522, #523) are folded into it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@Ark0N

Ark0N commented Oct 4, 2026

Copy link
Copy Markdown
Owner

Merged and shipped in 1.34.0. Thanks @irisitymichaelgrundberg! One gated --config model_reasoning_effort=<level> literal per level, rather than a new argv shape, is a neat use of the registry, and the golden test pinning the order with a model and a resume id is just what that needed.

The only change while landing was the @fileoverview nit in src/types/session.ts, which now lists all of CodexConfig's fields (06c4c7d).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants